「进阶0x43」你能回答这些问题吗
· 阅读需 3 分钟
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e5+10;
struct node
{
int l, r;
ll sum, dat, lmax, rmax;
node()
{
sum=0;
dat=lmax=rmax=-1e9;//初始化为一个小值,保证最终答案不小于此
}
}st[4*N];//完全树,开 4 倍的空间
int a[N];
ll max( ll a,ll b,ll c )//重载 max 便于代码简化
{
return max( max( a,b ),c );
}
void updata( node &p,node &x,node &y )//维护结点 p 与其左右两段 x,y 所对应的数据
{
p.sum=x.sum+y.sum;
// 前缀和即两儿子之和
p.lmax=max( x.lmax,x.sum+y.lmax );
// lmax(与左端相连的最大字段和)
// 是左儿子的 lmax 与
// 左儿子总值和右儿子的 lmax 的和中的较大值
p.rmax=max( y.rmax,y.sum+x.rmax );
// rmax(与右端相连的最大字段和)
// 是右儿子的 rmax 与
// 右儿子总值和左儿子的 rmax 的和中的较大值
p.dat=max( x.dat,y.dat,x.rmax+y.lmax );
// dat(最大子段和)
// 是左儿子的 dat 与
// 右儿子的 dat 与
// 相连后中间并出的最值(左儿子的 rmax + 右儿子的 lmax) 中的较大值
}
void build( int p,int l,int r )
{
st[p].l=l, st[p].r=r;
if( l == r )
{
st[p].lmax=st[p].rmax=st[p].dat=a[l];
st[p].sum=a[l];
// 当前一个格子的数据就为其本身
return ;
}
int mid=( l+r )>>1;
build( 2*p,l,mid );
build( 2*p+1,mid+1,r );
updata( st[p],st[2*p],st[2*p+1] );
}
void add( int p,int x,int v )
{
if( st[p].l == st[p].r )
{
st[p].lmax=st[p].rmax=st[p].dat=v;
st[p].sum=v;
return ;
}
int mid=( st[p].l+st[p].r )>>1;
if( mid >= x )
{
add( 2*p,x,v );
}
else
{
add( 2*p+1,x,v );
}
updata( st[p],st[2*p],st[2*p+1] );
}
node query( int p,int l,int r )
{
if( st[p].l >= l && st[p].r <= r )
{
return st[p];
}
int mid=( st[p].l+st[p].r )>>1;
node ans, a, b;
if( mid >= l )
{
a=query( 2*p,l,r );//a 存储着满足条件的左儿子的信息
}
if( mid < r )
{
b=query( 2*p+1,l,r );//b 存储着满足条件的右儿子的信息
}
updata( ans,a,b );//维护 ans 与其左儿子 a 和 右儿子 b
if( mid < l )//不存在左儿子时,只关注右儿子
{
ans.lmax=max( ans.lmax,b.lmax );
}
if( mid >= r )//不存在右儿子时,只关注左儿子
{
ans.rmax=max( ans.rmax,a.rmax );
}
return ans;//获得 ans 段的答案
}
int main() {
// freopen( "txt.in","r",stdin );
// freopen( ".out","w",stdout );
int n, m;
scanf( "%d%d",&n ,&m );
for( int i=1;i<=n;i++ )
{
scanf( "%d",&a[i] );
}
build( 1,1,n );
for( int i=1;i<=m;i++ )
{
int k, x, y;
scanf( "%d%d%d",&k ,&x ,&y );
if( k == 1 )
{
printf( "%lld\n",query( 1,min( x,y ),max( x,y ) ).dat );
}
else
{
add( 1,x,y );
}
}
return 0;
}
